#ifdef ENABLE_MAPLE_SAN

#ifndef MAPLE_SAN_INCLUDE_ASAN_PHASES_H
#define MAPLE_SAN_INCLUDE_ASAN_PHASES_H

#include <string>
#include <map>
#include "asan_function.h"
#include "maple_phase.h"
#include "san_common.h"
#include "maple_phase.h"
#include "maple_phase_manager.h"
#include "me_phase_manager.h"


namespace maple {
    MAPLE_FUNC_PHASE_DECLARE_BEGIN(MEDoVarCheck, MeFunction)
    PreAnalysis* GetResult();
    private:
        void GetAnalysisDependence(maple::AnalysisDep &aDep) const override;
        PreAnalysis* result = nullptr;
    MAPLE_FUNC_PHASE_DECLARE_END

    MAPLE_FUNC_PHASE_DECLARE_BEGIN(MEDoNeighborOpt, MeFunction)
    std::vector<AsanNodePos> GetResult();
    private:
        void GetAnalysisDependence(maple::AnalysisDep &aDep) const override;
        
        /* *Neighbor Checks Optimization* Begin */
        
        // for each indirect memory aceess statement, get the def of its address expression
        bool PreAnalysis(MeFunction &F);

        void NeighborOptEntry(BB *bb);
        void TraverseNodes(StmtNode *stmt, BaseNode *baseNode, std::vector<int> curDirections);
        const StmtNode * findDefStmt(BaseNode *baseNode, const VersionSt &vst);
        void filterRemovableMemAccesses();

        AddrofNode * getAddrofNode(BaseNode * baseNode);
        uint32 getOffset(BaseNode *baseNode);
        uint32 getStructOffset(BaseNode * node, MIRPtrType *ptrType, FieldID fieldID);
        uint32 getArrayOffset(BaseNode * node, MIRPtrType *ptrType, FieldID fieldID);
        void DumpIntermediateResult();
        void DumpResult();
        static bool cmp(std::pair<BaseNode *, int>& a, std::pair<BaseNode *, int>& b) {return a.second < b.second;}
        std::vector<std::pair<BaseNode *, int> > sortOffset();

        
        std::map<BaseNode * , uint32> node2offset;
        std::map<BaseNode * , size_t> node2size;
        std::map<BaseNode * , const StmtNode *> node2def;
        std::map<const StmtNode * , std::vector<BaseNode *>> def2nodes;
        
        std::map<BaseNode *, std::vector<int>> node2directions;
        std::map<BaseNode * , StmtNode *> node2stmt;

        std::vector<std::pair<SrcPosition, int>> result; // pos , size;
        
        std::vector<AsanNodePos> results;
    MAPLE_FUNC_PHASE_DECLARE_END

    MAPLE_FUNC_PHASE_DECLARE(MEDoAsan, MeFunction)
    MAPLE_FUNC_PHASE_DECLARE(MEASanRazor, MeFunction)

} // namespace maple

#endif // MAPLE_SAN_INCLUDE_SAN_PHASES_H

#endif